Skip to content

fix: use techmo-asr-api stubs instead of generating them at build time - #2

Merged
tomjad merged 4 commits into
masterfrom
feat/techmo-asr-api
Oct 22, 2026
Merged

tomjad merged 4 commits into
masterfrom
feat/techmo-asr-api

Conversation

@tomjad

@tomjad tomjad commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Installing the plugin fresh can produce a package that fails on import:

google.protobuf.runtime_version.VersionError: Detected incompatible Protobuf Gencode/Runtime versions
when loading techmo/asr/api/v1p1/asr.proto: gencode 7.x runtime 6.x

The hatch build hook generates *_pb2.py from proto/ using whatever grpcio-tools the build environment resolves (no upper bound). In an isolated build (the default for pip install) that is the newest grpcio-tools, whose protobuf gencode can be newer than the protobuf runtime the agent environment is constrained to. With livekit-agents==1.5.1, opentelemetry-proto caps protobuf at <7, so the stubs no longer import.

Reproduced on current master (0.2.0): a fresh install with livekit-agents==1.5.1 fails with the error above.

Change

Stubs from techmo-asr-api

Stubs now come from techmo-asr-api 1.1.4 (asr_api.v1p1), the same package the internal plugin uses. It ships them pre-generated with protobuf 5.29, so nothing is generated at install time.

  • removed hatch_build.py, proto/, livekit/plugins/techmo/_proto/ and the grpcio-tools build dependency; --no-build-isolation is no longer needed
  • stt.py: from asr_api import v1p1 as _proto. The alias name is kept, so the rest of the module is unchanged
  • dependencies: techmo-asr-api @ git+…@1.1.4 (not on PyPI yet, hence allow-direct-references), protobuf>=5.29.0 and grpcio>=1.70.0 (the stubs need a runtime ≥ gencode; they embed GRPC_GENERATED_VERSION = '1.70.0'), livekit-agents>=1.0,<2.0
  • README requirements aligned with the package metadata (they said livekit-agents >= 1.5, grpcio >= 1.63)

CI now actually runs

CI triggered on main, while the default branch is master, so it never ran on PRs. It now triggers on master. Enabling it exposed problems already present on master, fixed here so the pipeline is green:

  • removed the empty livekit/__init__.py and livekit/plugins/__init__.py. They made livekit a regular package, so an editable install (pip install -e ., as in CI) shadowed livekit.agents and 2 unit tests failed. livekit is now an implicit namespace package, like in the official LiveKit plugins; the wheel contents are unchanged
  • mypy: dropped the python_version = "3.10" pin (mypy aborted on numpy stubs using 3.12 syntax) and fixed the type errors it then reported. LanguageCode (livekit-agents ≥ 1.8 only) is ignored per line
  • ruff check --fix and format (unused imports, import order, formatting); isort configured to treat livekit.plugins.techmo as first-party inside the shared livekit namespace

mypy also flags _recognize_impl (override, union-attr). That is a real bug: STT.recognize() raises TypeError on conn_options. It is silenced with type: ignore here and fixed in #3 (stacked on this PR).

Verification

  • Same wire contract: descriptors of the removed proto/…/v1p1/asr.proto and techmo-asr-api's asr.proto compared (all messages, field names/numbers/types/labels, enums, rpc signatures): identical (78/78)
  • Fresh isolated install, livekit-agents==1.5.1: master fails with VersionError; this branch imports OK (protobuf 6.33.6). Also OK when installed from the git URL of this branch
  • protobuf range: asr_api.v1p1 imports with protobuf 5.29.5, 6.33.6 and 7.36.2; 5.28.3 fails (hence >=5.29.0)
  • grpcio floor: with grpcio 1.69.0 from asr_api import v1p1 raises RuntimeError (... depends on grpcio>=1.70.0); 1.70.0 imports OK
  • Wheel/sdist (isolated uv build): only plugin sources; Requires-Dist as above
  • CI-equivalent run in a clean Python 3.10 venv (editable install) with livekit-agents 1.8.8 and 1.5.1: ruff, ruff format, mypy clean; 18 unit tests pass. GitHub Actions: green on 3.10 / 3.11 / 3.12 + wheel build
  • Live ASR (streaming + batch, with session_id): transcripts OK. The responses from master and from this branch are the same, field by field

Known issues, not changed here

  • Batch transcript can come back empty when the service sends more than one final, e.g. a SUCCESS final with text followed by an empty NO_INPUT_TIMEOUT final. _recognize_impl overwrites the result with each final, so the last, empty one wins; the proto says clients should buffer an alternative from every final. Separate fix.
  • techmo-asr-api installs google/rpc/status_pb2.py, the same path as googleapis-common-protos (pulled in by livekit-agents through the OTLP exporter), so the two packages overwrite each other's file. To be fixed in asr-api-python.
  • The git-URL dependency blocks publishing to PyPI until techmo-asr-api is published there.

🤖 Generated with Claude Code

Tomasz Jadczyk and others added 4 commits September 30, 2026 12:52
The hatch build hook generated *_pb2.py from proto/ with whatever
grpcio-tools version the build environment resolved (no upper bound).
In an isolated build that is the newest grpcio-tools, whose protobuf
gencode can be newer than the protobuf runtime the agent environment
is constrained to (e.g. livekit-agents 1.5.1 -> opentelemetry-proto
<7 -> protobuf 6.x), so `import livekit.plugins.techmo` failed with
VersionError on fresh installs.

Take the stubs from techmo-asr-api 1.1.4 (asr_api.v1p1), which ships
them pre-generated with protobuf 5.29 and works with protobuf
5.29-7.x. Its asr.proto contract is identical to the removed proto/
copy (messages, fields, numbers, types, enums, rpc compared).

- remove hatch_build.py, proto/, _proto/ and the grpcio-tools build
  dependency; --no-build-isolation is no longer needed
- depend on techmo-asr-api by git URL (not on PyPI yet) and require
  protobuf>=5.29.0; cap livekit-agents <2.0
- CI, Makefile, .gitignore, README, CHANGELOG updated

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- techmo-asr-api 1.1.4 stubs embed GRPC_GENERATED_VERSION 1.70.0; with
  grpcio 1.69 `from asr_api import v1p1` raises RuntimeError, so the
  >=1.63.0 floor allowed broken installs
- README listed livekit-agents >= 1.5 and grpcio >= 1.63, disagreeing
  with the package metadata (>=1.0,<2.0) and the stubs (>=1.70)
- CI triggered on `main`, but the default branch is `master`, so it
  never ran for pull requests

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Enabling CI on master exposed problems already present on master:

- STT.recognize() raised TypeError: livekit-agents calls
  _recognize_impl(..., conn_options=...), which the plugin did not
  accept; a single AudioFrame buffer was also not iterable. Covered by a
  new test through the public recognize() API.
- Empty livekit/__init__.py and livekit/plugins/__init__.py made
  `livekit` a regular package, so with an editable install it shadowed
  livekit.agents and 2 unit tests failed. Removed (implicit namespace
  package, like the official livekit plugins); the wheel is unaffected.
- mypy pinned python_version 3.10 and aborted on numpy stubs using 3.12
  syntax; the pin is dropped and the type errors it then reported are
  fixed (LanguageCode in livekit-agents >=1.8 is ignored per line since
  older 1.x lacks it).
- ruff check --fix and ruff format; isort told that livekit.plugins.techmo
  is first-party within the shared livekit namespace.

Verified on Python 3.10 in a clean venv with livekit-agents 1.8.8 and
1.5.1: ruff, ruff format --check, mypy and 19 unit tests pass.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The batch recognize fix (conn_options argument, single AudioFrame
buffer) goes to a separate PR. Until then the two mypy errors it fixes
are silenced in _recognize_impl, so CI stays green.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@tomjad
tomjad merged commit 8257e2c into master Oct 22, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant